<?php
declare (strict_types=1);

namespace app\middleware;

use app\model\Shops;
use think\helper\Arr;
use think\helper\Str;
use think\Response;

class CheckShopifyRequest
{
    const SHARED_SECRET = 'hush';
    protected $whitelist = [
        '/api/v1/notify',
        '/api/v1/checkout/:id',
        '/api/v1/webhook',
        '/api/v1/test',
        '/api/v1/dashboard',
        '/api/v1/notify/:channel',
        '/api/v1/pixel/track',
    ];

    /**
     * 处理请求
     *
     * @param \think\Request $request
     * @param \Closure $next
     * @return Response
     */
    public function handle($request, \Closure $next)
    {
        try {
            $path = $request->url();
            if (Str::contains($path, '?')) {
                $path = Arr::first(explode('?', $path));
            }
            if ($this->isWhitelisted($path)) return $next($request);
            $shop = $request->header('X-Opc-Shop-Id');
            if (empty($shop)) throw new \Exception('miss shop host');
            $shop = Shops::query()->host($shop)->find();
            if (is_null($shop)) throw new \Exception('shop host not exists');
            $request->x_shop_id = $shop->id;
            $request->x_pay_step = $shop->pay_step;
            return $next($request);

        } catch (\Exception $e) {
            return Response::create(['code' => $e->getCode(), 'msg' => $e->getMessage()], 'json', $e->getCode());
        }
    }

    /**
     * 检查路径是否在白名单中
     * @param string $path
     * @return bool
     */
    protected function isWhitelisted(string $path): bool
    {
        // 直接匹配
        if (in_array($path, $this->whitelist)) {
            return true;
        }

        // 检查动态路由匹配 (例如 /api/v1/checkout/4 匹配 /api/v1/checkout/:id)
        foreach ($this->whitelist as $pattern) {
            if ($this->matchesPattern($path, $pattern)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 检查路径是否匹配给定的模式
     * @param string $path 实际路径
     * @param string $pattern 模式路径，如 /api/v1/checkout/:id
     * @return bool
     */
    protected function matchesPattern(string $path, string $pattern): bool
    {
        // 将模式中的 :param 转换为正则表达式
        $pattern = preg_quote($pattern, '/');
        $pattern = preg_replace('/\\\\:([^\\\\]+)/', '([^\/]+)', $pattern);
        $pattern = '/^' . $pattern . '$/';

        return (bool) preg_match($pattern, $path);
    }
}
